home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Magazin: Amiga-CD 1996 March
/
Amiga-CD 1996 #3.iso
/
demos
/
stormc-demo
/
examples
/
fplot
/
fclass.cc
next >
Wrap
C/C++ Source or Header
|
1996-01-19
|
6KB
|
330 lines
/*
Funktionsplotter in Storm C
Function-Modul
*/
#include <stream.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#include "fclass.h"
// Destruktoren:
Func::~Func() { } // Default: garnix
UnOpN::~UnOpN()
{ delete arg; }
BinOpN::~BinOpN()
{ delete l;
delete r;
}
// Konstruktoren:
double Func::Dummy;
KonstN::KonstN (double c)
{ Konst = c; }
UnOpN::UnOpN(UnOps op, Func *n):
oper(op), arg(n)
{ }
BinOpN::BinOpN(BinOps op, Func *ln, Func *rn):
oper(op), l(ln), r(rn)
{ }
// "Konstant"-Funktionen:
int Func::isconst (double &retval)
{ return 0; }
int KonstN::isconst (double &retval)
{ retval = Konst;
return 1;
}
// Ausgabe
#define EPANIC 26731
void KonstN::print(char*)
{
printf("%g", Konst);
}
void VarN::print(char*)
{ printf("x"); }
void ErrorN::print(char*)
{ printf("?"); }
void UnOpN::print(char* str)
{ switch(oper)
{ case Op_neg: printf("-"); break;
case Op_sqr: printf("sqr "); break;
case Op_sqrt: printf("sqrt "); break;
case Op_sin: printf("sin "); break;
case Op_cos: printf("cos "); break;
case Op_exp: printf("exp "); break;
case Op_ln: printf("ln "); break;
}
arg->print(str);
}
void BinOpN::print(char* str)
{ printf("(");
l->print(str);
switch (oper)
{ case Op_add: printf("+"); break;
case Op_sub: printf("-"); break;
case Op_mult:printf("*"); break;
case Op_div: printf("/"); break;
case Op_pot: printf("^"); break;
default: exit(EPANIC);
}
r->print(str);
printf(")");
}
// Auswertung
inline double sqr(double x)
{ return x*x; }
double intpotz(double base, int exp)
{ if (exp)
{ if (exp<0) return 1.0/intpotz(base,-exp)
else if (exp==1) return base;
else if (exp&1) return base*sqr(intpotz(base, exp/2));
else return sqr(intpotz(base, exp/2));
}
else return 1;
}
double UnOpN::eval (double x)
{
double y = arg->eval(x);
switch(oper)
{ case Op_neg: return -y;
case Op_sqr: return y*y;
case Op_sqrt: return sqrt(y);
case Op_sin: return sin(y);
case Op_cos: return cos(y);
case Op_exp: return exp(y);
case Op_ln: return log(y);
default: exit(EPANIC);
}
}
double BinOpN::eval (double x)
{ double lv = l->eval(x), rv = r->eval(x);
switch(oper)
{ case Op_add: return lv+rv;
case Op_sub: return lv-rv;
case Op_mult: return lv*rv;
case Op_div: return lv/rv;
case Op_pot: if (r->isconst() && floor(rv)==rv)
return intpotz(lv, int(rv))
else if (lv > 0) return exp(rv*log(lv));
return 0;
default: exit(EPANIC);
}
}
// ******** Parsing ********
#define EULER 2.7182818284
#define PI 3.141592653589
char *cp; // Zeiger auf String
char c; // gescanntes Zeichen
short ErrFlag; // Fehler aufgetreten?
char Get()
{ while ((c = *cp) == ' ')
cp++;
if(c) cp++;
return c;
}
Func *Fehler()
{ if (!ErrFlag)
{ cout << "\nError.\n";
ErrFlag = 1;
}
return new ErrorN;
}
Func *Expression();
Func *Term();
Func *Potenz();
Func *Factor()
{ while (c=='+') Get();
if (c=='x' || c=='X')
{ Get();
return new VarN;
}
else if (c >= '0' && c <= '9')
{
int i = 0;
enum {max = 80};
char numstr[max+1];
while (isdigit(c) && i<max)
{ numstr[i++] = c; Get(); }
if (c=='.')
{ numstr[i++] = c; Get(); }
while (isdigit(c) && i<max)
{ numstr[i++] = c; Get(); }
if (tolower(c)=='e')
{ numstr[i++] = c; Get();
if (c=='+' || c=='-')
{ numstr[i++] = c; Get(); }
else
if (!isdigit(c))
return Fehler();
while (isdigit(c) && i<max)
{ numstr[i++] = c; Get(); }
}
numstr[i]=0;
return new KonstN(atof(numstr));
}
else
if (c=='(')
{ Get();
Func *np = Expression();
if (c==')')
Get();
else
delete Fehler();
return np;
}
else
if (c=='c')
{ if (Get()=='o' && Get() == 's')
{ Get(); return new UnOpN(Op_cos, Factor()); }
else
return Fehler();
}
else
if (c=='e')
{ if (Get()!='x')
return new KonstN(EULER);
else if (Get() == 'p')
{ Get(); return new UnOpN(Op_exp, Factor()); }
else
return Fehler();
}
else if (c=='l')
{ if (Get()=='n')
return Get(), new UnOpN(Op_ln, Factor());
else
return Fehler();
}
else if (c=='p')
{ if (Get()!='i')
return Fehler();
Get(); return new KonstN(PI);
}
else if (c=='s')
{ Get();
if (c=='i')
{ if (Get() != 'n') return Fehler();
Get();
return new UnOpN(Op_sin, Factor());
}
else if (c=='q')
{ if (Get() != 'r') return Fehler();
if (Get()=='t')
{ Get();
return new UnOpN(Op_sqrt, Factor());
}
else return new UnOpN(Op_sqr, Factor());
}
else
return Fehler();
}
// Default-Ergebnis:
return Fehler();
}
Func *Potenz()
{
Func *n1 = Factor();
while (c=='^')
{ Get();
Func *n2 = Factor();
n1 = new BinOpN(Op_pot, n1, n2);
}
return n1;
}
Func *Term()
{ Func *n1 = Potenz();
while (c=='*' || c=='/')
{ BinOps op = c=='*'? Op_mult : Op_div;
Get();
Func *n2 = Potenz();
n1 = new BinOpN(op, n1, n2);
}
return n1;
}
Func *Expression()
{
if (c=='-')
{ Get();
Func *np = Term();
return new UnOpN(Op_neg,np);
}
else
{ Func *n1 = Term();
while (c=='+' || c=='-')
{ BinOps op = c=='+'? Op_add : Op_sub;
Get();
Func *n2 = Term();
n1 = new BinOpN(op, n1, n2);
}
return n1;
}
}
Func *Parse(char *string)
{ cp = string;
ErrFlag = 0;
Get();
Func *expr = Expression();
if (c) delete Fehler();
if(ErrFlag)
{ delete expr; return 0; }
else
return expr;
}